package cn.signalpha.modules.pay.controller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import cn.signalpha.common.constant.AppConstant;
import cn.signalpha.core.tool.jackson.JsonUtil;
import cn.signalpha.core.tool.utils.StringPool;
import cn.signalpha.core.tool.utils.StringUtil;
import cn.signalpha.modules.pay.enums.PayTypeEnum;
import cn.signalpha.modules.pay.provider.IPayGranter;
import cn.signalpha.modules.pay.provider.PayGranterBuilder;
import cn.signalpha.modules.pay.service.PayService;
import cn.signalpha.modules.shop.service.OrderRefundService;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApiConfigKit;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_PAY_NAME + "/notify")
@Api(value = "支付回调", tags = "支付回调")
public class PayNotifyController {

    private final PayService payService;
	private final OrderRefundService orderRefundService;

	@PostMapping(value="/order/ali")
	public String orderAliNotify(HttpServletRequest request) {
		Map<String, String> params = AliPayApi.toMap(request);
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.ALI_PAY.getType());
		if(payGranter.verifyNotify(params).equals(StringPool.TRUE)){
			String payNo = params.get("out_trade_no");
			String bizPayNo = params.get("trade_no");
			payService.orderPaySuccess(payNo, bizPayNo, PayTypeEnum.ALI_PAY.getType());
			return "success";
		}else{
			return "failure";
		}
	}
	@PostMapping("/order/wx")
	public String orderWxNotify(HttpServletRequest request) {
		String xmlMsg = HttpKit.readData(request);
		log.info("微信V2回调参数xml：{}", xmlMsg);
		Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
		log.info("微信V2回调参数params：{}", params);
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.WX_PAY.getType());
		if(payGranter.verifyNotify(params).equals(StringPool.TRUE)){
			String payNo = params.get("out_trade_no");
			String bizPayNo = params.get("transaction_id");
			payService.orderPaySuccess(payNo, bizPayNo, PayTypeEnum.WX_PAY.getType());
			Map<String, String> xml = new HashMap<>(2);
			xml.put("return_code", "SUCCESS");
			xml.put("return_msg", "OK");
			return WxPayKit.toXml(xml);
		}
		return null;
	}
	@PostMapping("/order/refund/wx")
	public String orderWxRefundNotify(HttpServletRequest request) {
		String xmlMsg = HttpKit.readData(request);
		log.info("微信V2退款回调参数xml：{}", xmlMsg);
		Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
		log.info("微信V2退款回调参数params：{}", params);
		if(WxPayKit.codeIsOk(params.get("return_code"))){
			String reqInfo = params.get("req_info");
			String decryptData = WxPayKit.decryptData(reqInfo, WxPayApiConfigKit.getWxPayApiConfig().getApiKey());
			Map<String, String> decryptDataMap = WxPayKit.xmlToMap(decryptData);
			String refundNo = decryptDataMap.get("out_refund_no");
			String refundBizNo = decryptDataMap.get("refund_id");
			String refundStatus = decryptDataMap.get("refund_status");
			orderRefundService.refundNotify(refundNo, refundBizNo, "SUCCESS".equals(refundStatus));
			Map<String, String> xml = new HashMap<>(2);
			xml.put("return_code", "SUCCESS");
			xml.put("return_msg", "OK");
			return WxPayKit.toXml(xml);
		}
		return null;
	}
	@PostMapping("/order/wx/v3")
	public void orderWxV3Notify(HttpServletRequest request, HttpServletResponse response) {
		String result = HttpKit.readData(request);
		log.info("微信V3回调参数：" + result);
		Map<String, String> verifyParams = new HashMap<>();
		verifyParams.put("timestamp", request.getHeader("Wechatpay-Timestamp"));
		verifyParams.put("nonce", request.getHeader("Wechatpay-Nonce"));
		verifyParams.put("serialNo", request.getHeader("Wechatpay-Serial"));
		verifyParams.put("signature", request.getHeader("Wechatpay-Signature"));
		verifyParams.put("result", result);
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.WX_PAY_V3.getType());
		String plainText = payGranter.verifyNotify(verifyParams);
		Map<String, String> responseMap = new HashMap<>(12);
		if(StringUtil.isNotBlank(plainText)){
			log.info("微信V3解密参数：" + plainText);
			Map<String, Object> params = JsonUtil.toMap(plainText);
			String payNo = MapUtil.getStr(params, "out_trade_no");
			String bizPayNo = MapUtil.getStr(params, "transaction_id");
			payService.orderPaySuccess(payNo, bizPayNo, PayTypeEnum.WX_PAY_V3.getType());
			response.setStatus(200);
			responseMap.put("code", "SUCCESS");
			responseMap.put("message", "SUCCESS");
		}else{
			response.setStatus(500);
			responseMap.put("code", "FAIL");
			responseMap.put("message", "失败");
		}
		try {
			response.setHeader("Content-type", ContentType.JSON.toString());
			response.getOutputStream().write(JSONUtil.toJsonStr(responseMap).getBytes(StandardCharsets.UTF_8));
			response.flushBuffer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	@PostMapping("/order/refund/wx/v3")
	public void orderWxV3RefundNotify(HttpServletRequest request, HttpServletResponse response) {
		String result = HttpKit.readData(request);
		log.info("微信V3退款回调参数：" + result);
		Map<String, String> verifyParams = new HashMap<>();
		verifyParams.put("timestamp", request.getHeader("Wechatpay-Timestamp"));
		verifyParams.put("nonce", request.getHeader("Wechatpay-Nonce"));
		verifyParams.put("serialNo", request.getHeader("Wechatpay-Serial"));
		verifyParams.put("signature", request.getHeader("Wechatpay-Signature"));
		verifyParams.put("result", result);
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.WX_PAY_V3.getType());
		String plainText = payGranter.verifyNotify(verifyParams);
		Map<String, String> responseMap = new HashMap<>(12);
		if(StringUtil.isNotBlank(plainText)){
			log.info("微信V3退款解密参数：" + plainText);
			Map<String, Object> params = JsonUtil.toMap(plainText);
			String refundNo = MapUtil.getStr(params, "out_refund_no");
			String refundBizNo = MapUtil.getStr(params, "refund_id");
			String refundStatus = MapUtil.getStr(params, "refund_status");
			orderRefundService.refundNotify(refundNo, refundBizNo, "SUCCESS".equals(refundStatus));
			response.setStatus(200);
			responseMap.put("code", "SUCCESS");
			responseMap.put("message", "SUCCESS");
		}else{
			response.setStatus(500);
			responseMap.put("code", "FAIL");
			responseMap.put("message", "失败");
		}
		try {
			response.setHeader("Content-type", ContentType.JSON.toString());
			response.getOutputStream().write(JSONUtil.toJsonStr(responseMap).getBytes(StandardCharsets.UTF_8));
			response.flushBuffer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	@RequestMapping("/order/join")
	public String orderJoinNotify(@RequestParam Map<String, String> params) {
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.JOIN_PAY_WX.getType());
		if(payGranter.verifyNotify(params).equals(StringPool.TRUE)){
			String payNo = params.get("r2_OrderNo");
			String bizPayNo = params.get("r7_TrxNo");
			String payType;
			if("ALIPAY".equals(params.get("rc_BankCode"))){
				payType = PayTypeEnum.JOIN_PAY_ALI.getType();
			}else{
				payType = PayTypeEnum.JOIN_PAY_WX.getType();
			}
			payService.orderPaySuccess(payNo, bizPayNo, payType);
			return "success";
		}
		return "failure";
	}
	@RequestMapping("/order/join/fast")
	public String orderJoinFastNotify(@RequestBody Map<String, String> params) {
		IPayGranter payGranter = PayGranterBuilder.getGranter(PayTypeEnum.JOIN_PAY_FAST.getType());
		if(payGranter.verifyNotify(params).equals(StringPool.TRUE)){
			Map<String, Object> resultDataMap = JsonUtil.toMap(String.valueOf(params.get("data")));
			String payNo = String.valueOf(resultDataMap.get("mch_order_no"));
			String bizPayNo = String.valueOf(resultDataMap.get("jp_order_no"));
			payService.orderPaySuccess(payNo, bizPayNo, PayTypeEnum.JOIN_PAY_FAST.getType());
			return "success";
		}
		return "failure";
	}


}
